﻿using Admin.NET.Application.Const;
using Admin.NET.Application.Entity;
using Admin.NET.Application.Helper;
using Admin.NET.Application.Service.ModbusTcp;
using Admin.NET.Core.Service;
using AngleSharp.Dom;
using DocumentFormat.OpenXml.Vml.Office;
using DotNetty.Buffers;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NewLife;
using NewLife.Data;
using NewLife.Net;
using NewLife.Net.Modbus1;
using Org.BouncyCastle.Utilities;
using SKIT.FlurlHttpClient.Wechat.Api.Models;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using static Admin.NET.Application.Service.ModbusTcpService.ModbusTcpService;

namespace Admin.NET.Application.Service.ModbusTcpService;

public partial class ModbusTcpService : IHostedService, IDisposable
{
    private readonly ILogger<ModbusTcpService> _logger;
    private readonly IServiceScopeFactory serviceScopeFactory;
    private readonly IServiceProvider service;
    private Timer _timer;
    private readonly SqlSugarRepository<DeviceInfo> _deviceInfoRep;
    private IChannel serverChannel;

    public ModbusTcpService(ILogger<ModbusTcpService> logger, IServiceProvider service)
    {
        _logger = logger;
        this.service = service;
        this.serviceScopeFactory = this.service.GetRequiredService<IServiceScopeFactory>();
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        await Task.Delay(1000);
        _logger.LogInformation("后台任务服务正在启动。");
        var bossGroup = new MultithreadEventLoopGroup(1);
        var workerGroup = new MultithreadEventLoopGroup();
        var configService = App.GetService<SysConfigService>();
        var modbusInfoManager = service.GetService<ModbusInfoManager>();
        var deviceInfoService = App.GetService<DeviceInfoService>();
        modbusInfoManager.DeviceInfos = await deviceInfoService.GetAllDeviceInfo();
        modbusInfoManager.InitModbusConnectInfoByDeviceInfo();

        try
        {
            var bootstrap = new ServerBootstrap();
            bootstrap.Group(bossGroup, workerGroup)
                     .Channel<TcpServerSocketChannel>()
                     .Option(ChannelOption.SoBacklog, 100)
                     .ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel =>
                     {
                         // 增加锁，防止多线程操作时出现问题
                         lock (this)
                         {
                             IChannelPipeline pipeline = channel.Pipeline;

                             //pipeline.AddLast(new ServerHandler());
                             //pipeline.AddLast(service.GetService<ServerHandler2>());
                             using (var scope = serviceScopeFactory.CreateScope())
                             {
                                 var serverHandler2 = scope.ServiceProvider.GetRequiredService<ServerHandler2>();
                                 pipeline.AddLast(serverHandler2);
                                 //帮我打印出serverHandler2对象的地址
                                 Console.WriteLine(serverHandler2.GetHashCode());
                             }
                         }
                     }));

            // 指定监听的 IP 地址和端口
            var ip = await configService.GetConfigValue<string>(ApplicationConfigConst.ModbusServerIp);
            if (string.IsNullOrEmpty(ip))
            {
                ip = "127.0.0.1";
            }
            var ipAddress = IPAddress.Parse(ip); // 替换为你想要监听的 IP 地址
            var port = 502;
            serverChannel = await bootstrap.BindAsync(new IPEndPoint(ipAddress, port));

            // 获取监听的 IP 和端口号
            var localEndPoint = serverChannel.LocalAddress as IPEndPoint;
            if (localEndPoint != null)
            {
                _logger.LogInformation($"服务器正在监听 IP: {localEndPoint.Address}, 端口: {localEndPoint.Port}");
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "后台任务服务启动失败。");
        }
    }

    private void DoWork(object state)
    {
        _logger.LogInformation("后台任务正在运行。");
        // 在这里执行你的任务逻辑
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("后台任务服务正在停止。");

        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

public class ServerHandler2 : ChannelHandlerAdapter, ITransient
{
    private readonly ModbusInfoManager modbusInfoManager;
    private readonly ILogger<ServerHandler2> logger;
    private readonly ReportProcess reportProcess;

    private readonly IServiceScopeFactory serviceScopeFactory;
    public static int ServerHandlerCount = 0;

    public ServerHandler2(ModbusInfoManager modbusInfoManager, IServiceScopeFactory serviceScopeFactory)
    {
        this.modbusInfoManager = modbusInfoManager;

        this.serviceScopeFactory = serviceScopeFactory;

        using (var scope = serviceScopeFactory.CreateScope())
        {
            logger = scope.ServiceProvider.GetRequiredService<ILogger<ServerHandler2>>();
            reportProcess = scope.ServiceProvider.GetRequiredService<ReportProcess>();
        }

        Console.WriteLine("创建了ServerHandler2");
        ServerHandlerCount++;
    }

    ~ServerHandler2()
    {
        ServerHandlerCount--;
        Console.WriteLine("销毁了ServerHandler2");
    }

    public override async void ChannelRead(IChannelHandlerContext context, object message)
    {
        try
        {
            var byteBuffer = message as IByteBuffer;
            if (byteBuffer == null)
            {
                return;
            }
            byte[] receivedBytes = new byte[byteBuffer.ReadableBytes];
            byteBuffer.GetBytes(byteBuffer.ReaderIndex, receivedBytes);

            if (receivedBytes.Length == 1)
            {
                return;
            }

            var modbusConnectInfo = modbusInfoManager.ModbusConnectInfos.FirstOrDefault(u => u.ChannelHandlerContext == context);
            var remoteAddress = context.Channel.RemoteAddress as IPEndPoint;
            var clientIp = remoteAddress.Address.ToString();
            var clientPort = remoteAddress.Port;
            // 从context获取ip和端口号

            modbusInfoManager.AddLogger($"iP:{clientIp},接收数据：{receivedBytes.ToHex()}");
            reportProcess.Process(modbusConnectInfo, receivedBytes, context);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "ChannelRead Error");
        }
    }

    public override void ChannelActive(IChannelHandlerContext context)
    {
        try
        {
            base.ChannelActive(context);
            // Console.WriteLine("ChannelActive,ServerHandler2Count=" + ServerHandler2.ServerHandlerCount + ",ModbusInfoCount=" + modbusInfoManager.ModbusConnectInfos.Count);
            // 获取连接的ip 和port
            var ipPort = GetChanelIpPort(context);
            if (string.IsNullOrEmpty(ipPort.Item1))
                return;

            var clientIp = ipPort.Item1;
            var clientPort = ipPort.Item2;
            modbusInfoManager.AddLogger($"IP:{clientIp}  Client connected");
            //查找 ModbusConnectInfos里是否有对应的ip和端口号的对象，如果没有则创建
            var info = modbusInfoManager.ModbusConnectInfos.FirstOrDefault(u => u.ChannelHandlerContext == context);
        }
        catch (Exception ex)
        {
            modbusInfoManager.AddLogger("ChannelActive Error " + ex.Message);
        }
        finally
        {
        }
    }

    public override async void ChannelInactive(IChannelHandlerContext context)
    {
        try
        {
            base.ChannelInactive(context);

            var ipPort = GetChanelIpPort(context);
            if (string.IsNullOrEmpty(ipPort.Item1))
                return;

            var clientIp = ipPort.Item1;
            var clientPort = ipPort.Item2;

            //查找 ModbusConnectInfos里是否有对应的ip和端口号的对象，如果没有则创建
            modbusInfoManager.AddLogger($"IP:{clientIp} Client disconnected");
            var modbusConnectInfo = modbusInfoManager.ModbusConnectInfos.FirstOrDefault(u => u.ChannelHandlerContext == context);
            if (modbusConnectInfo != null)
            {
                modbusConnectInfo.ModbusConnectStatus = ModbusConnectStatus.Disconnected;
                modbusConnectInfo.ChannelHandlerContext = null;
            }

            var DeviceLogInput = new AddDeviceLogInput
            {
                Ip = ipPort.Item1,
                ReceiveText = "客户端下线",
                Title = "断开",
            };

            if (modbusConnectInfo != null && !string.IsNullOrEmpty(modbusConnectInfo.Sn))
            {
                var deviceInfo = modbusInfoManager.GetDeviceInfo(modbusConnectInfo);
                if (deviceInfo != null)
                {
                    using (var scope = serviceScopeFactory.CreateScope())
                    {
                        var deviceOnOffLineService = scope.ServiceProvider.GetRequiredService<DeviceOnOffLineService>();
                        await deviceOnOffLineService.AddNoThrow(new AddDeviceOnOffLineInput
                        {
                            DeviceId = deviceInfo.Id,
                            GateWayId = deviceInfo.DeviceGateWayId,
                            IsOnline = IsOnline.Offline,
                            CreateTime = DateTime.Now,
                            OffLineReason = "网关下线"
                        });
                    }
                }
            }

            // 从列表中移除

            using (var scope = serviceScopeFactory.CreateScope())
            {
                var deviceLogService = scope.ServiceProvider.GetRequiredService<DeviceLogService>();
                await deviceLogService.AddNoThrow(DeviceLogInput);
            }
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "ChannelInactive Error");
        }
        finally
        {
        }
    }

    public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
    {
        logger.LogInformation($"Exception: {exception.Message}");
        context.CloseAsync();
    }

    private static Tuple<string, int> GetChanelIpPort(IChannelHandlerContext channelHandlerContext)
    {
        var remoteAddress = channelHandlerContext.Channel.RemoteAddress as IPEndPoint;
        if (remoteAddress != null)
        {
            var clientIp = remoteAddress.Address.ToString();
            var clientPort = remoteAddress.Port;
            return Tuple.Create(clientIp, clientPort);
        }
        return Tuple.Create("", 0);
    }
}

public class ModbusInfoManager : ISingleton
{
    public List<ModbusConnectInfo> ModbusConnectInfos = new List<ModbusConnectInfo>();
    public List<DeviceInfo> DeviceInfos = new List<DeviceInfo>();

    /// <summary>
    /// 队列消费
    /// </summary>
    public ConcurrentQueue<AddDeviceLogInput> AddDeviceLogQueue = new ConcurrentQueue<AddDeviceLogInput>();

    /// <summary>
    ///  异常指令队列消费
    /// </summary>
    public ConcurrentQueue<AddDeviceErrorCommandLogInput> AddErrorCommandQueue = new ConcurrentQueue<AddDeviceErrorCommandLogInput>();

    /// <summary>
    ///  点位更新队列
    /// </summary>
    public ConcurrentQueue<(long, DeviceSlaveTemplatePoints, string, ReadValueType, string, DateTime)> ValueUpDateQueue = new ConcurrentQueue<(long, DeviceSlaveTemplatePoints, string, ReadValueType, string, DateTime)>();

    /// <summary>
    ///  日志队列
    /// </summary>
    public ConcurrentQueue<(string, DateTime)> LoggerQuene = new ConcurrentQueue<(string, DateTime)>();

    // 当前正在查看的user
    public ConcurrentBag<(long, long, DateTime)> UserLookfor = new ConcurrentBag<(long, long, DateTime)>();

    private readonly ILogger<ModbusInfoManager> logger;
    private readonly IServiceProvider serviceProvider;

    public ModbusInfoManager(ILogger<ModbusInfoManager> logger, IServiceProvider serviceProvider)
    {
        Task.Run(ProcessQueueAsync);
        this.logger = logger;
        this.serviceProvider = serviceProvider;
        Task.Run(ContinueJob);
    }

    //初始化对应模型
    public void InitModbusConnectInfoByDeviceInfo()
    {
        foreach (var item in DeviceInfos)
        {
            if (!ModbusConnectInfos.Any(u => u.Sn == item.DeviceGateWay.Sn))
            {
                ModbusConnectInfos.Add(new ModbusConnectInfo
                {
                    Sn = item.DeviceGateWay.Sn,
                    ModbusConnectStatus = ModbusConnectStatus.Disconnected,
                });
            }
        }
    }

    public DeviceInfo GetDeviceInfo(ModbusConnectInfo modbusConnectInfo)
    {
        if (modbusConnectInfo == null)
        {
            return null;
        }
        return DeviceInfos.FirstOrDefault(u => !string.IsNullOrEmpty(modbusConnectInfo.Sn) && modbusConnectInfo.Sn.Contains(u.DeviceGateWay.Sn));
    }

    public Tuple<ModbusConnectInfo, DeviceInfo> GetModbusConnectInfoByDeviceId(long? deviceId)
    {
        if (deviceId == null)
        {
            return Tuple.Create<ModbusConnectInfo, DeviceInfo>(null, null);
        }

        var deviceInfo = DeviceInfos.FirstOrDefault(u => u.Id == deviceId.Value);
        ModbusConnectInfo connectInfo = null;
        if (deviceInfo != null)
        {
            connectInfo = ModbusConnectInfos.FirstOrDefault(u => u.Sn == deviceInfo.DeviceGateWay.Sn);
        }
        return Tuple.Create(connectInfo, deviceInfo);
    }

    /// <summary>
    ///  添加设备日志
    /// </summary>
    /// <param name="addDeviceLogInput"></param>
    public void AddDeviceLog(AddDeviceLogInput addDeviceLogInput)
    {
        addDeviceLogInput.CreateTime = DateTime.Now;
        AddDeviceLogQueue.Enqueue(addDeviceLogInput);
    }

    public void AddErrorCommand(ModbusConnectInfo modbusConnectInfo, byte[] command, string title = "验证错误的指令")
    {
        var deviceInfo = GetDeviceInfo(modbusConnectInfo);
        if (modbusConnectInfo == null || deviceInfo == null)
        {
            return;
        }

        var deviceErrorCommandLogService = App.GetService<DeviceErrorCommandLogService>();
        AddErrorCommandQueue.Enqueue(new AddDeviceErrorCommandLogInput
        {
            DeviceId = deviceInfo.Id,
            Title = title,
            ReceiveText = command.ToHex(),
            Ip = modbusConnectInfo.Ip,
            CreateTime = DateTime.Now
        });
    }

    public void AddLogger(string message)
    {
        LoggerQuene.Enqueue((message, DateTime.Now));
    }

    public void UpdataPointValue(long deviceId, DeviceSlaveTemplatePoints point, string value, ReadValueType readValueType, string oldValue)
    {
        point.DataValue = value;
        point.GetValueTime = DateTime.Now;
        point.UpdateTime = DateTime.Now;
        ValueUpDateQueue.Enqueue((deviceId, point, value, readValueType, oldValue, DateTime.Now));
    }

    #region 在线用户

    public void OnlineUserHealthCheck(long userId, long deviceId)
    {
        //查看是否有这个用户
        var user = UserLookfor.FirstOrDefault(u => u.Item1 == userId && u.Item2 == deviceId);
        //用户不存在则新增
        if (user.Item1 == 0)
        {
            UserLookfor.Add((userId, deviceId, DateTime.Now));
        }
        else
        {
            //用户存在则更新时间
            UserLookfor = new ConcurrentBag<(long, long, DateTime)>(UserLookfor.Where(u => u.Item1 != userId && u.Item2 != deviceId));
            UserLookfor.Add((userId, deviceId, DateTime.Now));
        }
    }

    //判断时间是否过期，过期则删除
    public void RemoveUserLookfor()
    {
        UserLookfor = new ConcurrentBag<(long, long, DateTime)>(UserLookfor.Where(u => (DateTime.Now - u.Item3).TotalMinutes < 5));
    }

    #endregion 在线用户

    private async Task ProcessQueueAsync()
    {
        StringBuilder sb = new StringBuilder();
        await Task.Delay(3000);
        while (true)
        {
            try
            {
                var itemsLog = new List<(string, DateTime)>();
                while (LoggerQuene.TryDequeue(out var item))
                {
                    itemsLog.Add(item);
                }
                if (itemsLog.Count > 0)
                {
                    sb.Clear();
                    //将items一次性打印出来,按照时间+信息+换行

                    foreach (var item in itemsLog)
                    {
                        sb.AppendLine($"{item.Item2.ToString("yyyy-MM-dd HH:mm:ss")}:{item.Item1}+\r\n");
                    }
                    logger.LogInformation(sb.ToString());
                }

                var itemsDeviceLog = new List<AddDeviceLogInput>();
                while (AddDeviceLogQueue.TryDequeue(out var item))
                {
                    itemsDeviceLog.Add(item);
                }

                if (itemsDeviceLog.Count > 0)
                {
                    using (var scope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
                    {
                        var deviceLogService = scope.ServiceProvider.GetRequiredService<DeviceLogService>();
                        await deviceLogService.AddDeviceLogList(itemsDeviceLog);
                    }
                }

                var itemsErrorCommand = new List<AddDeviceErrorCommandLogInput>();
                while (AddErrorCommandQueue.TryDequeue(out var item))
                {
                    itemsErrorCommand.Add(item);
                }

                if (itemsErrorCommand.Count > 0)
                {
                    using (var scope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
                    {
                        var deviceErrorCommandLogService = scope.ServiceProvider.GetRequiredService<DeviceErrorCommandLogService>();
                        await deviceErrorCommandLogService.AddDeviceErrorCommandLogList(itemsErrorCommand);
                    }
                }

                var itemsValueUpDate = new List<(long, DeviceSlaveTemplatePoints, string, ReadValueType, string, DateTime)>();
                while (ValueUpDateQueue.TryDequeue(out var item))
                {
                    itemsValueUpDate.Add(item);
                }

                if (itemsValueUpDate.Count > 0)
                {
                    using (var scope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
                    {
                        var deviceValueService = scope.ServiceProvider.GetRequiredService<DevicePointsValueService>();
                        foreach (var item in itemsValueUpDate)
                        {
                            var (deviceId, point, value, readValueType, oldValue, creatTime) = item;
                            await deviceValueService.UpdataPointValueByProcess(deviceId, point, value, readValueType, oldValue, creatTime);
                        }
                    }
                }
                await Task.Delay(1000); // 如果队列为空，等待一段时间再检查
            }
            catch (Exception ex)
            {
            }
        }
    }

    public Task ContinueJob()
    {
        return Task.Run(async () =>
        {
            await Task.Delay(10000);
            try
            {
                while (true)
                {
                    try
                    {
                        foreach (var item in ModbusConnectInfos)
                        {
                            var deviceInfo = GetDeviceInfo(item);
                            if (deviceInfo == null || item.ChannelHandlerContext == null || item.ModbusConnectStatus != ModbusConnectStatus.Connected)
                            {
                                continue;
                            }

                            await Task.Run(async () =>
                            {
                                foreach (var slave in deviceInfo.DeviceRelSlaves)
                                {
                                    foreach (var point in slave.DeviceSlaveTemplate.DeviceSlaveTemplatePoint)
                                    {
                                        if (point.Cycle == CycleType.NoCollection)
                                        {
                                            continue;
                                        }

                                        if (point.GetValueTime == null || (DateTime.Now - point.GetValueTime.Value).TotalMinutes > (int)point.Cycle)
                                        {
                                            //主动采集一次
                                            try
                                            {
                                                var result = item.ReadByPoint(point, slave.SlaveAddr);
                                                var resultStr = item.ReadValueToString(result);
                                                //更新数据
                                                UpdataPointValue(slave.DeviceInfoId, point, resultStr, ReadValueType.TimingCollect, point.DataValue);
                                            }
                                            catch (Exception ex)
                                            {
                                                var logger = App.GetService<ILogger<ModbusTcpService>>();
                                                logger.LogInformation(ex.Message);
                                            }
                                        }
                                    }
                                }
                            });
                        }
                        var deviceLogService = App.GetService<DeviceLogService>();
                        await deviceLogService.TrimDeviceLog();
                        var deviceErrorCommandLogService = App.GetService<DeviceErrorCommandLogService>();
                        await deviceErrorCommandLogService.TrimDeviceErrorCommandLog();
                        //一分钟执行一次
                        await Task.Delay(59000);
                    }
                    catch (Exception ex)
                    {
                        //遇到异常就休息5s重新获取
                        logger.LogError(ex, "");
                        await Task.Delay(10000);
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "");
            }
        });
    }

    /// <summary>
    /// 外界更新时调用设备更新
    /// </summary>
    /// <param name="deviceID"></param>
    public async Task RefreshDeviceByDeviceId(List<DeviceInfo> deviceInfos)
    {
        //查找 ModbusConnectInfos里是否有对应的ip和端口号的对象，如果没有则创建
        await RefreshAllDevice(deviceInfos);
    }

    public async Task RefreshAllDevice(List<DeviceInfo> deviceInfos)
    {
        DeviceInfos = deviceInfos;
        //断开所有设备
        var newInfoList = new List<ModbusConnectInfo>();
        foreach (var item in DeviceInfos)
        {
            if (!newInfoList.Any(u => u.Sn == item.DeviceGateWay.Sn))
            {
                newInfoList.Add(new ModbusConnectInfo
                {
                    Sn = item.DeviceGateWay.Sn,
                    ModbusConnectStatus = ModbusConnectStatus.Disconnected,
                });
            }
        }
        var oldList = ModbusConnectInfos;
        ModbusConnectInfos = newInfoList;
        foreach (var item in oldList)
        {
            if (item.ChannelHandlerContext != null)
            {
                await item.ChannelHandlerContext?.CloseAsync();
            }
        }
    }
}

public class ReportProcess : ITransient
{
    private readonly DeviceInfoService deviceInfoService;

    //接收的数据缓存list 用于解析
    private List<byte> receivedBytes = new List<byte>();

    public ModbusInfoManager ModbusInfoManager { get; }

    public ReportProcess(ModbusInfoManager modbusInfoManager, DeviceInfoService deviceInfoService, SysNoticeService sysNoticeService)
    {
        ModbusInfoManager = modbusInfoManager;
        this.deviceInfoService = deviceInfoService;
    }

    public async void Process(ModbusConnectInfo modbusConnectInfo, byte[] bytes, IChannelHandlerContext context)
    {
        var deviceInfo = ModbusInfoManager.GetDeviceInfo(modbusConnectInfo);
        //获取context ip
        var remoteAddress = context.Channel.RemoteAddress as IPEndPoint;
        var clientIp = remoteAddress.Address.ToString();

        lock (this)
        {
            //将数据放入缓存
            receivedBytes.AddRange(bytes);
            //receivedBytes用CTDHeader这个指令头进行分割
            // 将缓存的字节数组转换为字符串
            string receivedString = Encoding.ASCII.GetString(receivedBytes.ToArray());

            // 定义匹配 CTD + 15位数字的正则表达式
            string pattern = @"CTD\d{15}";

            // 使用正则表达式找到所有匹配的位置
            MatchCollection matches = Regex.Matches(receivedString, pattern);

            if (matches.Count == 0)
            {
                return;
            }

            List<int> headerPositions = new List<int>();

            foreach (Match match in matches)
            {
                // 记录每个头部的起始索引
                headerPositions.Add(match.Index);
            }
            //本次已经处理过的数据
            List<byte[]> hasProcessData = new List<byte[]>();
            // 根据头部位置提取数据
            for (int i = 0; i < headerPositions.Count; i++)
            {
                int start = headerPositions[i] + 18; // 跳过头部，18个字符

                int length;

                if (i + 1 < headerPositions.Count)
                {
                    // 有下一个头部，长度为下一个头部的位置减去当前数据起始位置
                    length = headerPositions[i + 1] - start;
                }
                else
                {
                    // 没有下一个头部，取到字符串末尾
                    length = receivedString.Length - start;
                }

                if (length > 0)
                {
                    string data = receivedString.Substring(start, length);
                    //把data转成byte数组
                    byte[] dataBytes = receivedBytes.Skip(start).Take(length).ToArray();
                    //判断数据是否被处理过
                    if (hasProcessData.Any(data => data.SequenceEqual(dataBytes)))
                    {
                        continue;
                    }
                    hasProcessData.Add(dataBytes);
                    //判断数据是否被处理过

                    var sn = receivedString.Substring(3, 15);
                    if (modbusConnectInfo == null)
                    {
                        modbusConnectInfo = AsyncToSync.RunSync(() =>
                        {
                            return ProcessConnecting(sn, context);
                        });
                    }

                    if (modbusConnectInfo != null)
                    {
                        ProcessConnected(modbusConnectInfo, dataBytes);
                    }
                    else
                    {
                    }

                    //删除receivedBytes当前包的数据
                }
            }
            receivedBytes.Clear();
            hasProcessData.Clear();
        }
    }

    public async Task<ModbusConnectInfo> ProcessConnecting(string sn, IChannelHandlerContext context)
    {
        // 将byte数组转utf8
        ModbusConnectInfo modbusConnectInfo = ModbusInfoManager.ModbusConnectInfos.FirstOrDefault(u => sn.Replace("CTD", "") == (u.Sn.Replace("CTD", "")));
        //根据sn和pwd 获取网关
        var deviceInfo = ModbusInfoManager.GetDeviceInfo(modbusConnectInfo);
        if (deviceInfo != null)
        {
            modbusConnectInfo.ModbusConnectStatus = ModbusConnectStatus.Connected;
            modbusConnectInfo.ChannelHandlerContext = context;
            //更新设备在线状态
            var deviceOnOffLineService = App.GetService<DeviceOnOffLineService>();
            await deviceOnOffLineService.AddNoThrow(new AddDeviceOnOffLineInput
            {
                DeviceId = deviceInfo.Id,
                GateWayId = deviceInfo.DeviceGateWayId,
                IsOnline = IsOnline.Online,
                CreateTime = DateTime.Now,
                OffLineReason = "网关上线"
            });
        }

        if (modbusConnectInfo != null)
        {
            modbusConnectInfo.Ip = ((IPEndPoint)context.Channel.RemoteAddress).Address.ToString();
        }

        return modbusConnectInfo;
    }

    /// <summary>
    /// 连接之后时候的处理
    /// </summary>
    /// <param name="modbusConnectInfo"></param>
    /// <param name="receivedBytes"></param>
    public void ProcessConnected(ModbusConnectInfo modbusConnectInfo, byte[] receivedBytes)
    {
        var deviceInfo = ModbusInfoManager.GetDeviceInfo(modbusConnectInfo);
        try
        {
            //小于6个字节的不处理
            if (receivedBytes.Length < 6)
            {
                return;
            }

            var pk = new Packet(receivedBytes);
            var rs = new ModbusEntity();
            rs = rs.Parse(pk.Data, pk.Offset, pk.Count);
            //crc校验
            var crc = pk.Data.Crc(pk.Offset, pk.Total - 2);
            if (crc != rs.Crc)
            {
                rs.SetError(Errors.CrcError);
                // ModbusInfoManager.AddErrorCommand(modbusConnectInfo, receivedBytes, "crc校验错误：" + crc);
                ModbusInfoManager.AddDeviceLog(new AddDeviceLogInput
                {
                    Ip = modbusConnectInfo.Ip,
                    ReceiveText = receivedBytes.ToHex(),
                    Title = deviceInfo?.DeviceGateWay?.GateWayName + "",
                    GateWayId = deviceInfo?.DeviceGateWay?.Id,
                    DeviceId = deviceInfo?.Id,
                    DeviceProcotolProessResult = DeviceProcotolProessResult.CrcError
                });
                return;
            }
            if (modbusConnectInfo.MyMaster.IsSendToDevice)
            {
                ModbusInfoManager.AddLogger($"iP: {modbusConnectInfo.Ip} ,接收数据：{receivedBytes.ToHex()}");
            }

            //数据主动上报
            if ((int)rs.Function > 0X40)
            {
                MyMaster myMaster = modbusConnectInfo.MyMaster;
                myMaster.ChannelHandlerContext = modbusConnectInfo.ChannelHandlerContext;
                myMaster.ModbusEntity = rs;
                myMaster.ProcessForReport(rs);
                var host = rs.Host;

                var reportEntity = new ReportEntity();
                if (!reportEntity.Parse(rs))
                {
                    //ModbusInfoManager.AddErrorCommand(modbusConnectInfo, receivedBytes, "上报数据不符合规范");
                    ModbusInfoManager.AddDeviceLog(new AddDeviceLogInput
                    {
                        Ip = modbusConnectInfo.Ip,
                        ReceiveText = receivedBytes.ToHex(),
                        Title = deviceInfo?.DeviceGateWay?.GateWayName + "",
                        GateWayId = deviceInfo?.DeviceGateWay?.Id,
                        DeviceId = deviceInfo?.Id,
                        DeviceProcotolProessResult = DeviceProcotolProessResult.ReportDataError
                    });
                    return;
                }

                //符合要求就先返回
                var slave = deviceInfo.DeviceRelSlaves.FirstOrDefault(u => u.SlaveAddr == host);
                if (slave == null)
                {
                    //ModbusInfoManager.AddErrorCommand(modbusConnectInfo, receivedBytes, "没有配置对应的从机");
                    ModbusInfoManager.AddDeviceLog(new AddDeviceLogInput
                    {
                        Ip = modbusConnectInfo.Ip,
                        ReceiveText = receivedBytes.ToHex(),
                        Title = deviceInfo?.DeviceGateWay?.GateWayName + "",
                        GateWayId = deviceInfo?.DeviceGateWay?.Id,
                        DeviceId = deviceInfo?.Id,
                        DeviceProcotolProessResult = DeviceProcotolProessResult.NoSlaveConfig
                    });
                    return;
                }
                switch (rs.Function)
                {
                    case MBFunction.ReportCoils:
                        ProcessReportCoils(modbusConnectInfo, slave, reportEntity, modbusConnectInfo.MyMaster);
                        break;

                    case MBFunction.ReportInputs:
                        ProcessReportInputs(modbusConnectInfo, slave, reportEntity, modbusConnectInfo.MyMaster);
                        break;

                    case MBFunction.ReportHoldingRegisters:
                        ProcessReportHoldingRegisters(modbusConnectInfo, slave, reportEntity, modbusConnectInfo.MyMaster);
                        break;

                    case MBFunction.ReportInputRegisters:
                        ProcessReportInputRegisters(modbusConnectInfo, slave, reportEntity, modbusConnectInfo.MyMaster);
                        break;

                    default:
                        break;
                }

                ModbusInfoManager.AddDeviceLog(new AddDeviceLogInput
                {
                    Ip = modbusConnectInfo.Ip,
                    ReceiveText = receivedBytes.ToHex(),
                    Title = deviceInfo?.DeviceGateWay?.GateWayName + "",
                    GateWayId = deviceInfo?.DeviceGateWay?.Id,
                    DeviceId = deviceInfo?.Id,
                    DeviceProcotolProessResult = DeviceProcotolProessResult.Success
                });
            }
            else
            {
                modbusConnectInfo.MyMaster.IsReplied = true;
                modbusConnectInfo.MyMaster.ModbusEntity = rs;

                ModbusInfoManager.AddDeviceLog(new AddDeviceLogInput
                {
                    Ip = modbusConnectInfo.Ip,
                    ReceiveText = receivedBytes.ToHex(),
                    Title = deviceInfo?.DeviceGateWay?.GateWayName + "",
                    GateWayId = deviceInfo?.DeviceGateWay?.Id,
                    DeviceId = deviceInfo?.Id,
                    DeviceProcotolProessResult = DeviceProcotolProessResult.SendReply
                });
            }
        }
        catch (Exception ex)
        {
            ModbusInfoManager.AddDeviceLog(new AddDeviceLogInput
            {
                Ip = modbusConnectInfo.Ip,
                ReceiveText = ex.Message + ":" + receivedBytes.ToHex(),
                Title = deviceInfo?.DeviceGateWay?.GateWayName + "",
                GateWayId = deviceInfo?.DeviceGateWay?.Id,
                DeviceId = deviceInfo?.Id,
                DeviceProcotolProessResult = DeviceProcotolProessResult.OtherError
            });
        }
    }

    #region 上报处理

    /// <summary>
    /// 处理上报线圈
    /// </summary>
    /// <param name="modbusConnectInfo"></param>
    /// <param name="slave"></param>
    /// <param name="rs"></param>
    /// <returns></returns>
    private void ProcessReportCoils(ModbusConnectInfo modbusConnectInfo, DeviceRelSlave slave, ReportEntity reportEntity, MyMaster myMaster, RegType regType = RegType.Coil)
    {
        var addrCoil = reportEntity.StartAddress;
        var countCoil = reportEntity.PacketCount;
        var dataCoil = myMaster.ByteArrayToBoolArray(reportEntity.DataArray);
        foreach (var point in slave.DeviceSlaveTemplate.DeviceSlaveTemplatePoint.Where(u => u.RegType == regType))
        {
            var index = int.Parse(point.reg) - 1 - addrCoil;
            if (index >= 0 && index < countCoil)
            {
                // await UpdataPointValue(slave.DeviceInfoId, point, dataCoil[index] + "");
                ModbusInfoManager.UpdataPointValue(slave.DeviceInfoId, point, dataCoil[index] + "", ReadValueType.ReportCollect, point.DataValue);
                ////更新 modbusConnectInfo里面对应的值
                //var currentPoint = modbusConnectInfo.DeviceInfo.DeviceRelSlaves.FirstOrDefault(u => u.SlaveAddr == reportEntity.Host).DeviceSlaveTemplate.DeviceSlaveTemplatePoint.FirstOrDefault(u => u.Id == point.Id);
                //currentPoint.DataValue = point.DataValue;
            }
        }
    }

    /// <summary>
    /// 处理上报输入线圈
    /// </summary>
    /// <param name="modbusConnectInfo"></param>
    /// <param name="slave"></param>
    /// <param name="rs"></param>
    /// <returns></returns>
    private void ProcessReportInputs(ModbusConnectInfo modbusConnectInfo, DeviceRelSlave slave, ReportEntity rs, MyMaster myMaster)
    {
        ProcessReportCoils(modbusConnectInfo, slave, rs, myMaster, RegType.DiscreteInput);
    }

    /// <summary>
    /// 处理上报保持寄存器
    /// </summary>
    /// <param name="modbusConnectInfo"></param>
    /// <param name="slave"></param>
    /// <param name="rs"></param>
    /// <returns></returns>
    private void ProcessReportHoldingRegisters(ModbusConnectInfo modbusConnectInfo, DeviceRelSlave slave, ReportEntity rs, MyMaster myMaster, RegType regType = RegType.HoldingRegister)
    {
        var addrHolding = rs.StartAddress;
        var countHolding = rs.PacketCount;
        var dataHolding = rs.DataArray;
        foreach (var point in slave.DeviceSlaveTemplate.DeviceSlaveTemplatePoint.Where(u => u.RegType == regType))
        {
            var pointAddr = Convert.ToInt16(point.reg) - 1;
            if (pointAddr < addrHolding || pointAddr > addrHolding + countHolding)
            {
                continue;
            }
            var dataLength = modbusConnectInfo.GetDataLengthByPointType(point.DataType);

            //获取pointAddr在dataHolding中的索引
            var index = (pointAddr - addrHolding);
            //获取pointAddr的数据
            var data = dataHolding.Skip(index * 2).Take(dataLength * 2).ToArray();
            if (data.Length != dataLength)
            {
                return;
            }
            //将data 转化成十进制
            var value = ByteArrayToInt(data);
            ModbusInfoManager.UpdataPointValue(slave.DeviceInfoId, point, value + "", ReadValueType.ReportCollect, point.DataValue);
        }
    }

    /// <summary>
    /// 处理上报输入寄存器
    /// </summary>
    /// <param name="modbusConnectInfo"></param>
    /// <param name="slave"></param>
    /// <param name="rs"></param>
    /// <returns></returns>
    private void ProcessReportInputRegisters(ModbusConnectInfo modbusConnectInfo, DeviceRelSlave slave, ReportEntity rs, MyMaster myMaster)
    {
        ProcessReportHoldingRegisters(modbusConnectInfo, slave, rs, myMaster, RegType.InputRegister);
    }

    public int ByteArrayToInt(byte[] byteArray)
    {
        if (byteArray == null || byteArray.Length == 0 || byteArray.Length > 4)
        {
            //todo 这里抛异常后shutdown
            return 0;
        }

        int result = 0;
        for (int i = 0; i < byteArray.Length; i++)
        {
            result |= byteArray[i] << (8 * (byteArray.Length - 1 - i));
        }

        return result;
    }

    #endregion 上报处理
}